home *** CD-ROM | disk | FTP | other *** search
- unit IndexBob;
- {$I-}
- interface
- const
- MaxPage = 255;
-
- type
- TNumPage = 0..MaxPage; { max number of webpages in site }
- TURLPage = ShortString { assuming URL <= 255 characters };
-
- var
- WebPages: TNumPage = 0;
- WebPage: Array[TNumPage] of TURLPage;
-
- const
- MaxKeyword = 31;
-
- type
- TKeyword = String[MaxKeyword];
- TPageSet = Set of TNumPage;
-
- function Pages(PageSet: TPageSet): Byte;
-
- type
- TNode = record
- Keyword: TKeyword; { 32 bytes }
- URLs: TPageSet; { 32 bytes }
- end {TNode};
-
- TTree = class
- Node: TNode;
- constructor Create;
- destructor Destroy; override;
- function FindKeywordInPages(const KeyWord: TKeyword): TPageSet;
- private
- Prev,Next: TTree;
- end {TTree};
-
- var
- Keywords: Integer = 0;
- root: TTree = nil;
-
- type
- TIndexFile = File of TNode;
-
- implementation
-
- function Pages(PageSet: TPageSet): Byte;
- var
- B: Byte;
- begin
- Result := 0;
- for B := 0 to MaxPage do
- if B in PageSet then Result := Result + 1
- end {Pages};
-
- constructor TTree.Create;
- begin
- inherited Create;
- Prev := nil;
- Next := nil;
- {$IFDEF NULL}
- FillChar(Node.Keyword,MaxKeyword+1,#0); { sparse }
- Node.URLs := []
- {$ENDIF}
- end {Create};
-
- destructor TTree.Destroy;
- begin
- if Prev <> nil then Prev.Free;
- if Next <> nil then Next.Free;
- inherited Destroy
- end {Destroy};
-
- function TTree.FindKeywordInPages(const Keyword: TKeyword): TPageSet;
- var
- tmp: TTree;
- begin
- Result := [];
- tmp := root;
- repeat
- if tmp.Node.Keyword > Keyword then
- tmp := tmp.Prev
- else
- if tmp.Node.Keyword < Keyword then
- tmp := tmp.Next
- until (tmp = nil) or (tmp.Node.Keyword = Keyword);
- if tmp <> nil then
- Result := tmp.Node.URLs
- end {FindKeywordInPages};
-
-
- function CreateRoot(depth: Integer): TTree;
- var
- r: TTree;
- begin
- if depth > 0 then
- begin
- r := TTree.Create;
- r.Prev := CreateRoot(depth-1);
- r.Next := CreateRoot(depth-1);
- CreateRoot := r
- end
- else CreateRoot := nil
- end {CreateRoot};
-
- procedure CreateLeafs(var number: Integer; root: TTree);
- begin
- if root.Prev <> nil then
- begin
- CreateLeafs(number,root.Prev);
- if number > 0 then CreateLeafs(number,root.Next)
- end
- else
- begin
- root.Prev := TTree.Create;
- Dec(number);
- if number > 0 then
- begin
- root.Next := TTree.Create;
- Dec(number)
- end
- end
- end {CreateLeafs};
-
- procedure ReadNode(var IndexFile: TIndexFile; root: TTree);
- begin
- if root.Prev <> nil then ReadNode(IndexFile, root.Prev);
- read(IndexFile,root.Node);
- Inc(Keywords);
- if root.Next <> nil then ReadNode(IndexFile, root.Next)
- end {ReadNode};
-
- var
- PageFile: Text;
- IndexFile: TIndexFile;
- total,depth,i: Integer;
-
- initialization
- writeln('content-type: text/html');
- writeln;
- writeln('<HTML>');
- writeln('<BODY BACKGROUND="/gif/back.gif">');
- writeln('<H2>IndexBob</H2>');
- writeln('IndexBob is my Website Search Engine, entirely written in Borland Delphi (the source code even compiles with Delphi 2).');
- writeln('The search engine is topic of a 2-part <I>Under Construction</I> column in the Jan/Feb issues of The Delphi Magazine.');
- writeln('<BR>');
- writeln('Ultimately, the search engine should support multiple keyword search, combined with <B>AND</B>, <B>OR</B> and <B>NOT</B> abilities.');
- writeln('For now, you can only search for a single keyword, however...');
- writeln('<P>');
- writeln('<FORM METHOD="POST" ACTION="/cgi-bin/indexbob.exe">');
- writeln('<TABLE>');
- writeln('<TR><TD><I>Search again:</I></TD>');
- writeln('<TD><INPUT TYPE="TEXT" NAME="Keyword" SIZE=29></TD></TR>');
- writeln('<TR><TD></TD><TD>');
- writeln('<INPUT TYPE="SUBMIT" VALUE="Search">');
- writeln('<INPUT TYPE="RESET" VALUE="Reset"></TD></TR>');
- writeln('</TABLE>');
- writeln('</FORM>');
- writeln('Feedback is welcome in my newsgroup <A HREF="news://news.shoresoft.com/drbob.internet.tools">drbob.internet.tools</A>.');
- writeln('<HR>');
- assign(PageFile,'pages.bob');
- reset(PageFile);
- if IOResult = 0 then
- begin
- while not eof(PageFile) do
- begin
- readln(PageFile,WebPage[WebPages]);
- Inc(WebPages)
- end;
- close(PageFile)
- end;
- assign(IndexFile,'index.bob');
- reset(IndexFile);
- total := FileSize(IndexFile);
- if IOResult = 0 then
- begin
- if total = 1 then root := TTree.Create
- else {total > 1}
- begin
- depth := 0;
- i := 1;
- repeat
- i := i SHL 1;
- Inc(depth)
- until i >= total;
- Dec(depth);
- i := total - (i SHR 1) + 1;
- root := CreateRoot(depth);
- if i > 0 then CreateLeafs(i, root)
- end;
- if total > 0 then
- ReadNode(IndexFile, root);
- close(IndexFile)
- end
- finalization
- writeln('<HR>');
- writeln('<FONT SIZE=1>');
- writeln('Webpages: ',WebPages);
- writeln('<BR>Keywords: ',Keywords);
- writeln('</FONT>');
- writeln('<HR>');
- writeln('</BODY>');
- writeln('</HTML>');
- root.Free
- end.
-